package de.bht.netviz.useradm.dao;

import de.bht.netviz.dao.exceptions.NonexistentEntityException;
import de.bht.netviz.useradm.model.RegisteredUser;
import de.bht.netviz.useradm.model.RegisteredUser_;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityNotFoundException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

/**
 * JPA Controller für die Klasse RegisteredUser
 * @author Marius Hentschel
 * @since  2012/011/06
 */
public class RegisteredUserJpaController implements Serializable {

   public RegisteredUserJpaController(EntityManagerFactory emf) {
      this.emf = emf;
   }
   private EntityManagerFactory emf = null;

   public EntityManager getEntityManager() {
      return emf.createEntityManager();
   }

   public void create(RegisteredUser registeredUser) {
      EntityManager em = null;
      try {
         em = getEntityManager();
         em.getTransaction().begin();
         em.persist(registeredUser);
         em.getTransaction().commit();
      } finally {
         if (em != null) {
            em.close();
         }
      }
   }

   public void edit(RegisteredUser registeredUser) throws NonexistentEntityException {
      EntityManager em = null;
      try {
         em = getEntityManager();
         em.getTransaction().begin();
         registeredUser = em.merge(registeredUser);
         em.getTransaction().commit();
      } catch (Exception ex) {
         String msg = ex.getLocalizedMessage();
         if (msg == null || msg.length() == 0) {
            long id = registeredUser.getId();
            if (findRegisteredUser(id) == null) {
               throw new NonexistentEntityException("The registeredUser with id " + id + " no longer exists.");
            }
         }
         throw ex;
      } finally {
         if (em != null) {
            em.close();
         }
      }
   }

   public void destroy(long id) throws NonexistentEntityException {
      EntityManager em = null;
      try {
         em = getEntityManager();
         em.getTransaction().begin();
         RegisteredUser registeredUser;
         try {
            registeredUser = em.getReference(RegisteredUser.class, id);
            registeredUser.getId();
         } catch (EntityNotFoundException enfe) {
            throw new NonexistentEntityException("The registeredUser with id " + id + " no longer exists.", enfe);
         }
         em.remove(registeredUser);
         em.getTransaction().commit();
      } finally {
         if (em != null) {
            em.close();
         }
      }
   }

   public List<RegisteredUser> findRegisteredUserEntities() {
      return findRegisteredUserEntities(true, -1, -1);
   }

   public List<RegisteredUser> findRegisteredUserEntities(int maxResults, int firstResult) {
      return findRegisteredUserEntities(false, maxResults, firstResult);
   }

   private List<RegisteredUser> findRegisteredUserEntities(boolean all, int maxResults, int firstResult) {
      EntityManager em = getEntityManager();
      try {
         CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
         cq.select(cq.from(RegisteredUser.class));
         Query q = em.createQuery(cq);
         if (!all) {
            q.setMaxResults(maxResults);
            q.setFirstResult(firstResult);
         }
         return q.getResultList();
      } finally {
         em.close();
      }
   }

   public RegisteredUser findRegisteredUser(long id) {
      EntityManager em = getEntityManager();
      try {
         return em.find(RegisteredUser.class, id);
      } finally {
         em.close();
      }
   }

   public int getRegisteredUserCount() {
      EntityManager em = getEntityManager();
      try {
         CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
         Root<RegisteredUser> rt = cq.from(RegisteredUser.class);
         cq.select(em.getCriteriaBuilder().count(rt));
         Query q = em.createQuery(cq);
         return ((Long) q.getSingleResult()).intValue();
      } finally {
         em.close();
      }
   }
   
   /**
    * Sucht einen registrierten User über den Usernamen.
    * 
    * @param username
    *    Der Username des gesuchten Users.
    * @return 
    *    das RegisteredUser Objekt oder NULL, falls der Username nicht gefunden wurde.
    */
   public RegisteredUser findByUsername( String username ) {
      RegisteredUser retVal = null;
      
      
      CriteriaBuilder qb = this.emf.getCriteriaBuilder();
      CriteriaQuery<RegisteredUser> c = qb.createQuery(RegisteredUser.class);
      Root<RegisteredUser> p = c.from(RegisteredUser.class);
      Predicate condition = qb.equal(p.get(RegisteredUser_.username), username);
      c.where(condition);
      TypedQuery<RegisteredUser> q = this.emf.createEntityManager().createQuery(c); 
      List<RegisteredUser> result = q.getResultList();
      
      if( result != null ) {
         switch( result.size() ) {
            case 1:
               retVal = result.get(0);
               break;
            case 0:
            default:
               retVal = null;
         }
      }
      return retVal;
   }
   
   /**
    * Sucht einen registrierten User über den Usernamen mit Passwort
    * 
    * @param username
    *    Der Username des zu verifizierenden Users.
    * @param passwordHash 
    *    Das zum Username gehörige Passwort
    * @return 
    *    das RegisteredUser Objekt oder NULL, falls der Username nicht gefunden 
    *    wurde, oder das Passwort falsch war.
    *   
    */
   public RegisteredUser verifyPassword( String username, String passwordHash ) {
      RegisteredUser retVal = null;
      
      
      CriteriaBuilder qb = this.emf.getCriteriaBuilder();
      CriteriaQuery<RegisteredUser> c = qb.createQuery(RegisteredUser.class);
      Root<RegisteredUser> p = c.from(RegisteredUser.class);
      Predicate condition = qb.equal(p.get(RegisteredUser_.username), username);
      Predicate c2 = qb.equal(p.get(RegisteredUser_.passHash), passwordHash);
      c.where(condition);
      c.where(c2);
      TypedQuery<RegisteredUser> q = this.emf.createEntityManager().createQuery(c); 
      List<RegisteredUser> result = q.getResultList();
      
      if( result != null ) {
         switch( result.size() ) {
            case 1:
               retVal = result.get(0);
               break;
            case 0:
            default:
               retVal = null;
         }
      }
      return retVal;
   }
}
